package com.clouddms.service.transfer;

import com.clouddms.service.common.IService;
import com.clouddms.service.common.ServiceStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 传输性能监控服务
 * 监控文件传输性能，提供统计分析和性能优化建议
 *
 * @author Cloud-DMS Team
 * @version 1.0.0
 */
@Slf4j
@Service
public class TransferPerformanceMonitor implements IService {

    // 传输会话监控
    private final Map<String, TransferSession> activeSessions = new ConcurrentHashMap<>();
    
    // 性能统计
    private final AtomicLong totalTransfers = new AtomicLong(0);
    private final AtomicLong totalBytes = new AtomicLong(0);
    private final AtomicLong totalTime = new AtomicLong(0);
    
    // 最近的传输记录（保留最近1000条）
    private final Queue<TransferRecord> recentTransfers = new ArrayDeque<>();
    private final Object recordLock = new Object();
    private static final int MAX_RECORDS = 1000;

    // === IService 接口实现 ===

    @Override
    public String getServiceName() {
        return "transferPerformanceMonitor";
    }

    @Override
    public String getDisplayName() {
        return "传输性能监控";
    }

    @Override
    public String getDescription() {
        return "监控文件传输性能指标，提供速度统计、瓶颈分析和性能优化建议";
    }

    @Override
    public ServiceStatus getStatus() {
        return ServiceStatus.DEBUGGING;
    }

    @Override
    public int getPriority() {
        return 45;
    }

    // === 传输监控方法 ===

    /**
     * 开始监控传输会话
     *
     * @param sessionId 会话ID
     * @param fileName 文件名
     * @param fileSize 文件大小
     * @param transferType 传输类型
     * @return 传输会话
     */
    public TransferSession startTransferSession(String sessionId, String fileName, 
                                               long fileSize, TransferType transferType) {
        TransferSession session = new TransferSession(sessionId, fileName, fileSize, transferType);
        activeSessions.put(sessionId, session);
        
        log.debug("开始监控传输会话: sessionId={}, fileName={}, size={}, type={}", 
            sessionId, fileName, fileSize, transferType);
        
        return session;
    }

    /**
     * 更新传输进度
     *
     * @param sessionId 会话ID
     * @param transferredBytes 已传输字节数
     */
    public void updateTransferProgress(String sessionId, long transferredBytes) {
        TransferSession session = activeSessions.get(sessionId);
        if (session != null) {
            session.updateProgress(transferredBytes);
        }
    }

    /**
     * 结束传输会话
     *
     * @param sessionId 会话ID
     * @param success 是否成功
     * @param errorMessage 错误信息（如果失败）
     */
    public void endTransferSession(String sessionId, boolean success, String errorMessage) {
        TransferSession session = activeSessions.remove(sessionId);
        if (session != null) {
            session.end(success, errorMessage);
            
            // 添加到历史记录
            addTransferRecord(session);
            
            // 更新统计
            totalTransfers.incrementAndGet();
            totalBytes.addAndGet(session.getTransferredBytes());
            totalTime.addAndGet(session.getDuration());
            
            log.info("传输会话结束: sessionId={}, success={}, speed={}KB/s, duration={}ms", 
                sessionId, success, session.getAverageSpeedKBps(), session.getDuration());
        }
    }

    /**
     * 获取活跃传输会话
     *
     * @return 活跃会话列表
     */
    public List<TransferSession> getActiveSessions() {
        return new ArrayList<>(activeSessions.values());
    }

    /**
     * 获取传输性能统计
     *
     * @return 性能统计信息
     */
    public TransferStatistics getTransferStatistics() {
        synchronized (recordLock) {
            return new TransferStatistics(
                totalTransfers.get(),
                totalBytes.get(),
                totalTime.get(),
                activeSessions.size(),
                calculateAverageSpeed(),
                getRecentAverageSpeed(60000), // 最近1分钟
                getRecentTransferRecords(100)
            );
        }
    }

    /**
     * 获取性能分析报告
     *
     * @return 性能分析报告
     */
    public PerformanceAnalysisReport getPerformanceAnalysis() {
        List<TransferRecord> records = getRecentTransferRecords(500);
        
        if (records.isEmpty()) {
            return new PerformanceAnalysisReport("暂无传输数据", Collections.emptyList(), Collections.emptyList());
        }

        List<String> insights = analyzePerformance(records);
        List<String> recommendations = generateRecommendations(records);
        
        return new PerformanceAnalysisReport("性能分析完成", insights, recommendations);
    }

    /**
     * 清理过期的传输记录
     */
    public void cleanupExpiredRecords() {
        synchronized (recordLock) {
            long cutoffTime = System.currentTimeMillis() - 24 * 60 * 60 * 1000; // 24小时前
            
            recentTransfers.removeIf(record -> record.getEndTime() < cutoffTime);
            
            log.debug("清理过期传输记录，当前记录数: {}", recentTransfers.size());
        }
    }

    // === 私有方法 ===

    /**
     * 添加传输记录
     */
    private void addTransferRecord(TransferSession session) {
        synchronized (recordLock) {
            TransferRecord record = new TransferRecord(
                session.getSessionId(),
                session.getFileName(),
                session.getFileSize(),
                session.getTransferredBytes(),
                session.getTransferType(),
                session.getStartTime(),
                session.getEndTime(),
                session.isSuccess(),
                session.getErrorMessage(),
                session.getAverageSpeedKBps()
            );
            
            recentTransfers.offer(record);
            
            // 保持记录数量限制
            while (recentTransfers.size() > MAX_RECORDS) {
                recentTransfers.poll();
            }
        }
    }

    /**
     * 计算总体平均速度
     */
    private double calculateAverageSpeed() {
        long total = totalTime.get();
        if (total <= 0) return 0.0;
        
        return (double) totalBytes.get() / (total / 1000.0) / 1024; // KB/s
    }

    /**
     * 计算最近时间窗口的平均速度
     */
    private double getRecentAverageSpeed(long timeWindowMs) {
        long cutoffTime = System.currentTimeMillis() - timeWindowMs;
        
        synchronized (recordLock) {
            long totalBytes = 0;
            long totalTime = 0;
            
            for (TransferRecord record : recentTransfers) {
                if (record.getEndTime() >= cutoffTime) {
                    totalBytes += record.getTransferredBytes();
                    totalTime += record.getDuration();
                }
            }
            
            if (totalTime <= 0) return 0.0;
            return (double) totalBytes / (totalTime / 1000.0) / 1024; // KB/s
        }
    }

    /**
     * 获取最近的传输记录
     */
    private List<TransferRecord> getRecentTransferRecords(int limit) {
        synchronized (recordLock) {
            return recentTransfers.stream()
                .sorted((r1, r2) -> Long.compare(r2.getEndTime(), r1.getEndTime()))
                .limit(limit)
                .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
        }
    }

    /**
     * 分析性能数据
     */
    private List<String> analyzePerformance(List<TransferRecord> records) {
        List<String> insights = new ArrayList<>();
        
        if (records.isEmpty()) return insights;

        // 成功率分析
        long successCount = records.stream().mapToLong(r -> r.isSuccess() ? 1 : 0).sum();
        double successRate = (double) successCount / records.size() * 100;
        insights.add(String.format("传输成功率: %.1f%%", successRate));

        // 速度分析
        double avgSpeed = records.stream().mapToDouble(TransferRecord::getAverageSpeed).average().orElse(0);
        insights.add(String.format("平均传输速度: %.1f KB/s", avgSpeed));

        // 文件大小分析
        long avgFileSize = (long) records.stream().mapToLong(TransferRecord::getFileSize).average().orElse(0);
        insights.add(String.format("平均文件大小: %s", formatBytes(avgFileSize)));

        // 传输类型分析
        Map<TransferType, Long> typeCount = new HashMap<>();
        for (TransferRecord record : records) {
            typeCount.merge(record.getTransferType(), 1L, Long::sum);
        }
        
        for (Map.Entry<TransferType, Long> entry : typeCount.entrySet()) {
            double percentage = (double) entry.getValue() / records.size() * 100;
            insights.add(String.format("%s: %.1f%%", entry.getKey().getDisplayName(), percentage));
        }

        return insights;
    }

    /**
     * 生成性能优化建议
     */
    private List<String> generateRecommendations(List<TransferRecord> records) {
        List<String> recommendations = new ArrayList<>();
        
        if (records.isEmpty()) return recommendations;

        // 基于成功率的建议
        long failedCount = records.stream().mapToLong(r -> r.isSuccess() ? 0 : 1).sum();
        if (failedCount > records.size() * 0.1) { // 失败率超过10%
            recommendations.add("传输失败率较高，建议检查网络连接和服务器状态");
        }

        // 基于速度的建议
        double avgSpeed = records.stream().mapToDouble(TransferRecord::getAverageSpeed).average().orElse(0);
        if (avgSpeed < 100) { // 速度低于100KB/s
            recommendations.add("传输速度较慢，建议使用分块上传或检查网络带宽");
        }

        // 基于文件大小的建议
        long maxFileSize = records.stream().mapToLong(TransferRecord::getFileSize).max().orElse(0);
        if (maxFileSize > 50 * 1024 * 1024) { // 大于50MB
            recommendations.add("存在大文件传输，建议启用分块上传和断点续传");
        }

        // 基于并发数的建议
        if (activeSessions.size() > 10) {
            recommendations.add("当前并发传输数较多，可能影响单个传输速度");
        }

        return recommendations;
    }

    /**
     * 格式化字节大小
     */
    private String formatBytes(long bytes) {
        if (bytes < 1024) return bytes + " B";
        int exp = (int) (Math.log(bytes) / Math.log(1024));
        String pre = "KMGTPE".charAt(exp - 1) + "";
        return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
    }

    // === 内部类 ===

    /**
     * 传输类型枚举
     */
    public enum TransferType {
        UPLOAD("上传"),
        DOWNLOAD("下载"),
        CHUNK_UPLOAD("分块上传"),
        RESUME_UPLOAD("断点续传");

        private final String displayName;

        TransferType(String displayName) {
            this.displayName = displayName;
        }

        public String getDisplayName() {
            return displayName;
        }
    }

    /**
     * 传输会话
     */
    public static class TransferSession {
        private final String sessionId;
        private final String fileName;
        private final long fileSize;
        private final TransferType transferType;
        private final long startTime;
        private long endTime;
        private long transferredBytes;
        private boolean success;
        private String errorMessage;

        public TransferSession(String sessionId, String fileName, long fileSize, TransferType transferType) {
            this.sessionId = sessionId;
            this.fileName = fileName;
            this.fileSize = fileSize;
            this.transferType = transferType;
            this.startTime = System.currentTimeMillis();
            this.transferredBytes = 0;
        }

        public void updateProgress(long transferredBytes) {
            this.transferredBytes = transferredBytes;
        }

        public void end(boolean success, String errorMessage) {
            this.endTime = System.currentTimeMillis();
            this.success = success;
            this.errorMessage = errorMessage;
        }

        public long getDuration() {
            return endTime > 0 ? endTime - startTime : System.currentTimeMillis() - startTime;
        }

        public double getProgress() {
            return fileSize > 0 ? (double) transferredBytes / fileSize * 100 : 0;
        }

        public double getAverageSpeedKBps() {
            long duration = getDuration();
            return duration > 0 ? (double) transferredBytes / (duration / 1000.0) / 1024 : 0;
        }

        // Getters
        public String getSessionId() { return sessionId; }
        public String getFileName() { return fileName; }
        public long getFileSize() { return fileSize; }
        public TransferType getTransferType() { return transferType; }
        public long getStartTime() { return startTime; }
        public long getEndTime() { return endTime; }
        public long getTransferredBytes() { return transferredBytes; }
        public boolean isSuccess() { return success; }
        public String getErrorMessage() { return errorMessage; }
    }

    /**
     * 传输记录
     */
    public static class TransferRecord {
        private final String sessionId;
        private final String fileName;
        private final long fileSize;
        private final long transferredBytes;
        private final TransferType transferType;
        private final long startTime;
        private final long endTime;
        private final boolean success;
        private final String errorMessage;
        private final double averageSpeed;

        public TransferRecord(String sessionId, String fileName, long fileSize, long transferredBytes,
                            TransferType transferType, long startTime, long endTime, boolean success,
                            String errorMessage, double averageSpeed) {
            this.sessionId = sessionId;
            this.fileName = fileName;
            this.fileSize = fileSize;
            this.transferredBytes = transferredBytes;
            this.transferType = transferType;
            this.startTime = startTime;
            this.endTime = endTime;
            this.success = success;
            this.errorMessage = errorMessage;
            this.averageSpeed = averageSpeed;
        }

        public long getDuration() { return endTime - startTime; }

        // Getters
        public String getSessionId() { return sessionId; }
        public String getFileName() { return fileName; }
        public long getFileSize() { return fileSize; }
        public long getTransferredBytes() { return transferredBytes; }
        public TransferType getTransferType() { return transferType; }
        public long getStartTime() { return startTime; }
        public long getEndTime() { return endTime; }
        public boolean isSuccess() { return success; }
        public String getErrorMessage() { return errorMessage; }
        public double getAverageSpeed() { return averageSpeed; }
    }

    /**
     * 传输统计信息
     */
    public static class TransferStatistics {
        private final long totalTransfers;
        private final long totalBytes;
        private final long totalTime;
        private final int activeTransfers;
        private final double averageSpeed;
        private final double recentAverageSpeed;
        private final List<TransferRecord> recentRecords;

        public TransferStatistics(long totalTransfers, long totalBytes, long totalTime, int activeTransfers,
                                double averageSpeed, double recentAverageSpeed, List<TransferRecord> recentRecords) {
            this.totalTransfers = totalTransfers;
            this.totalBytes = totalBytes;
            this.totalTime = totalTime;
            this.activeTransfers = activeTransfers;
            this.averageSpeed = averageSpeed;
            this.recentAverageSpeed = recentAverageSpeed;
            this.recentRecords = recentRecords;
        }

        // Getters
        public long getTotalTransfers() { return totalTransfers; }
        public long getTotalBytes() { return totalBytes; }
        public long getTotalTime() { return totalTime; }
        public int getActiveTransfers() { return activeTransfers; }
        public double getAverageSpeed() { return averageSpeed; }
        public double getRecentAverageSpeed() { return recentAverageSpeed; }
        public List<TransferRecord> getRecentRecords() { return recentRecords; }
    }

    /**
     * 性能分析报告
     */
    public static class PerformanceAnalysisReport {
        private final String summary;
        private final List<String> insights;
        private final List<String> recommendations;
        private final long timestamp;

        public PerformanceAnalysisReport(String summary, List<String> insights, List<String> recommendations) {
            this.summary = summary;
            this.insights = insights;
            this.recommendations = recommendations;
            this.timestamp = System.currentTimeMillis();
        }

        // Getters
        public String getSummary() { return summary; }
        public List<String> getInsights() { return insights; }
        public List<String> getRecommendations() { return recommendations; }
        public long getTimestamp() { return timestamp; }
    }
}